﻿using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using OAuth.Server.Domain.Entities;
using OAuth.Server.Domain;

namespace OAuth.Server.OAuth.Stores
{
    public class PersistedGrantStore : IPersistedGrantStore
    {
        private readonly GrantRepository _grantRepository;
        public PersistedGrantStore(GrantRepository grantRepository)
        {
            _grantRepository = grantRepository;
        }

        #region 对象转换
        private static PersistedGrant ToGrant(TGrant grant)
        {
            if (grant == null) return null;
            return new PersistedGrant
            {
                Key = grant.Id,
                Data = grant.Data,
                SubjectId = grant.SubjectId,
                ClientId = grant.ClientId,
                Type = grant.Type,
                CreationTime = grant.CreateTime,
                Expiration = grant.ExpiredTime
            };
        }

        private static TGrant ToEntity(PersistedGrant grant)
        {
            if (grant == null) return null;
            return new TGrant
            {
                Id = grant.Key,
                Data = grant.Data,
                SubjectId = grant.SubjectId,
                ClientId = grant.ClientId,
                Type = grant.Type,
                CreateTime = grant.CreationTime,
                ExpiredTime = grant.Expiration
            };
        }
        #endregion

        public Task StoreAsync(PersistedGrant grant)
        {
            var model = ToEntity(grant);
            return _grantRepository.InsertAsync(model);
        }

        public async Task<PersistedGrant> GetAsync(string key)
        {
            var model = await _grantRepository.QueryByIdAsync(key);
            return ToGrant(model);
        }

        public async Task<IEnumerable<PersistedGrant>> GetAllAsync(string subjectId)
        {
            var models = await _grantRepository.QueryBySubjectIdAsync(subjectId);
            return models.Select(ToGrant);
        }

        public async Task RemoveAsync(string key)
        {
            await _grantRepository.DeleteAsync(key);
        }

        public async Task RemoveAllAsync(string subjectId, string clientId)
        {
            await _grantRepository.DeleteBySubjectIdAsync(subjectId, clientId);
        }

        public async Task RemoveAllAsync(string subjectId, string clientId, string type)
        {
            await _grantRepository.DeleteBySubjectIdAsync(subjectId, clientId, type);
        }
    }
}
